#include "compiler.h"
#include <fstream>

Compiler::Compiler(const Config & config)
	:	m_config(&config), m_data(0)
{
}

Compiler::~Compiler()
{
	Clean();
}

void Compiler::ReadFile(const std::string & fv)
{
	std::ifstream fd(fv.c_str());
	fd >> m_version;
	fd >> m_width;
	fd >> m_height;
	unsigned int index;
	if(fd)
	{
		m_data.resize(m_width * m_height);		
		for(unsigned int line_nr = 0; line_nr < m_height; ++line_nr)
		{
			for(unsigned int col_nr = 0; col_nr < m_width; ++col_nr)
			{
				index = line_nr * m_width + col_nr;
				fd >> m_data[index];
				if(m_data[index] > 5)
				{
					throw std::exception("Unsupported Mesh number.");
				}
			}
		}
	}
	fd.close();
}

void Compiler::WriteHeader(std::ostream & fr) const
{
	fr.write("CEMF", sizeof(unsigned int));
	fr.write(reinterpret_cast< const char * >(&m_version), sizeof(unsigned int));
	fr.write(reinterpret_cast< const char * >(&m_width), sizeof(unsigned int));
	fr.write(reinterpret_cast< const char * >(&m_height), sizeof(unsigned int));
}

void Compiler::WriteData(std::ostream & fr) const
{
	fr.write(reinterpret_cast< const char * >(&m_data[0]), sizeof(unsigned short) * m_data.size());
}

void Compiler::Clean()
{
	m_data.clear();
}

void Compiler::Load(const std::string & fv)
{
	try
	{
		ReadFile(fv);
	}
	catch(...)
	{		
		Clean();
	}
		
}

void Compiler::Save(const std::string & dest) const
{
	std::ofstream fr(dest.c_str(), std::ios::out | std::ios::binary);
	if(fr)
	{
		WriteHeader(fr);
		WriteData(fr);
		fr.close();
	}
	else
	{
		throw std::exception("Error: Can not open file for writing.");
	}
}

std::string Compiler::Output(const std::string & input) const
{
	std::string output = m_config->Output();
	std::string::size_type lastSlash = input.find_last_of('\\');
	std::string::size_type lastDot = input.find_last_of('.');
	if(output == "")
	{
		output = input.substr(0, lastDot);
		output += ".cemf";
	}
	else if(output[output.length() - 1] == '\\')
	{
		output += input.substr(lastSlash + 1, lastDot - lastSlash - 1);
		output += ".cemf";
	}
	else if(output.rfind(".cemf") != output.length() - 5)
	{
		output += ".cemf";
	}
	return output;
}

void Compiler::Compile(const std::string & input)
{
	/*if(m_config->Verbose())
	{
		std::cout << "Compiling..." << std::endl;
	}*/
	Load(input);
	if(m_config->Check())
	{
		/*if(m_config->Verbose())
		{
			std::cout << "Check flag is present in the config - skiping output generation" << std::endl;
		}*/
		return;
	}
	std::string output = Output(input);
	/*if(m_config->Verbose())
	{
		std::cout << "Generating output..." << std::endl;
	}*/
	Save(output);
}

int Compiler::Run()
{
	std::list< std::string > inputFiles = m_config->Input();
	if(inputFiles.size() > 0)
	{
		for(std::list< std::string >::const_iterator it = inputFiles.begin(); it != inputFiles.end(); ++it)
		{
			Compile(*it);
		}
	}
	else
	{
		throw std::exception("Error: Nothing to compile.");
	}
	return 0;
}